﻿using System.Collections.Generic;
using System.Web.Mvc;
using InvoiceInvoker.Logic;
using InvoiceInvoker.Logic.Repositories;
using InvoiceInvoker.MvcUI.Helpers;
using InvoiceInvoker.MvcUI.Models;
using InvoiceInvoker.MvcUI.ViewModels;

namespace InvoiceInvoker.MvcUI.Controllers
{
	[Authorize]
	[HandleError]
    public class InvoicesController : Controller
    {
		private int _sellerId;
		private InvoiceRepository _invoiceRepository;
		private RegisteredCustomerRepository _customerRepository;
		private RegisteredProductRepository _productRepository;

		protected override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			this.SetSellerId();
			_sellerId = (int)Session["SellerId"];
			_invoiceRepository = new InvoiceRepository(_sellerId);
			_customerRepository = new RegisteredCustomerRepository(_sellerId);
			_productRepository = new RegisteredProductRepository(_sellerId);

			base.OnActionExecuting(filterContext);
		}

        //
        // GET: /Invoices/

		public ActionResult Index(InvoicesIndexViewModel viewModel)
        {
			if (viewModel.Filter == null)
				viewModel.Filter = new Filters.InvoicesFilter();

			viewModel.Invoices = _invoiceRepository.GetByExpression(viewModel.Filter.GetExpression()).ToInvoiceModelList();

            return View(viewModel);
        }

        //
        // GET: /Invoices/Details/5

        public ActionResult Details(int id)
        {
			InvoiceModel invoice = new InvoiceModel(_invoiceRepository.GetById(id));
			SetGeneralValues(id);

            return View(invoice);
        }

        //
        // GET: /Invoices/Create

        public ActionResult Create(int? patternId)
        {
			List<int> productIds = new List<int>();
			Dictionary<int, decimal> productQuantities = new Dictionary<int, decimal>();

			InvoiceModel invoice;

			if (patternId.HasValue)
			{
				InvoicePattern pattern = new InvoicePatternRepository(_sellerId).GetById(patternId.Value);

				foreach (var item in pattern.InvoicePatternRegisteredProducts)
				{
					productIds.Add(item.RegisteredProductId.Value);
					productQuantities.Add(item.RegisteredProductId.Value, 1);
				}

				invoice = new InvoiceModel(pattern);
			}
			else
			{
				invoice = new InvoiceModel(_sellerId);
			}

			Session["ProductIds"] = productIds;
			Session["ProductQuantities"] = productQuantities;

			InvoicesViewModel viewModel = new InvoicesViewModel
			{
				Invoice = invoice,
				Customers = _customerRepository.GetAll().ToCustomerModelList(),
				PaymentTypes = PaymentTypesProvider.GetPaymentTypes()
			};

            return View(viewModel);
        }

        //
        // POST: /Invoices/Create

        [HttpPost]
        public ActionResult Create(InvoicesViewModel viewModel)
        {
			List<int> productIds = Session["ProductIds"] as List<int>;
			Dictionary<int, decimal> productQuantities = Session["ProductQuantities"] as Dictionary<int, decimal>;

            if (ModelState.IsValid && productIds.Count > 0 && productQuantities.ContainsValue(0) == false)
            {
				_invoiceRepository.Add(viewModel.Invoice.ToInvoice(productIds, productQuantities));
				Session["ProductIds"] = null;
				Session["ProductQuantities"] = null;

                return RedirectToAction("Index");
            }
            else
            {
				if (productIds.Count == 0)
					ViewData["ErrorMessage"] = "Wybierz produkty";
				else
				{
					if (productQuantities.ContainsValue(0))
					ViewData["ErrorMessage"] = "Ilość musi być liczbą większą od 0";

					foreach (int productId in productIds)
					{
						viewModel.Invoice.Products.Add(_productRepository.GetById(productId).ToProduct(productQuantities[productId], true));
					}
				}

				viewModel.Customers = _customerRepository.GetAll().ToCustomerModelList();
				viewModel.PaymentTypes = PaymentTypesProvider.GetPaymentTypes();

				return View(viewModel);
            }
        }

        //
        // GET: /Invoices/Delete/5
 
        public ActionResult Delete(int id)
        {
			InvoiceModel invoice = new InvoiceModel(_invoiceRepository.GetById(id));
			SetGeneralValues(id);

            return View(invoice);
        }

        //
        // POST: /Invoices/Delete/5

        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
			_invoiceRepository.Remove(id);

			return RedirectToAction("Index");
        }

		//
		// GET: /Invoices/ToPdf/5

		public ActionResult ToPdf(int id, PdfCreator.InvoiceType invoiceType)
		{
			Invoice invoice = _invoiceRepository.GetById(id);
			string path = Server.MapPath("~/bin/lastInvoice.pdf");
			string fileName = invoice.CreationDate.Value.ToShortDateString() + "_" + invoice.Customer.CompanyName + ".pdf";

			PdfCreator pdfCreator = new PdfCreator(invoice);
			pdfCreator.Create(invoiceType);
			pdfCreator.SaveDocument(path, false);

			return File(path, "PDF|*.pdf", fileName);
		}

		//
		// GET: /Invoices/MarkAsPaid/5

		public ActionResult MarkAsPaid(int id)
		{
			_invoiceRepository.GetById(id).UpdateStatus(Invoice.InvoiceStatus.Paid);

			return RedirectToAction("Index");
		}

		private void SetGeneralValues(int id)
		{
			Invoice invoice = _invoiceRepository.GetById(id);

			List<string> vatRates = invoice.GetVatRates();
			List<string> netValues = new List<string>();
			List<string> vatValues = new List<string>();
			List<string> grossValues = new List<string>();

			foreach (string vatRate in vatRates)
			{
				netValues.Add(invoice.GetGeneralNetValue(vatRate).ToString("N"));
				vatValues.Add(invoice.GetGeneralVatValue(vatRate).ToString("N"));
				grossValues.Add(invoice.GetGeneralGrossValue(vatRate).ToString("N"));
			}

			vatRates.Insert(0, "X");
			netValues.Insert(0, invoice.GetGeneralNetValue().ToString("N"));
			vatValues.Insert(0, invoice.GetGeneralVatValue().ToString("N"));
			grossValues.Insert(0, invoice.GetGeneralGrossValue().ToString("N"));

			ViewData["VatRates"] = vatRates;
			ViewData["NetValues"] = netValues;
			ViewData["VatValues"] = vatValues;
			ViewData["GrossValues"] = grossValues;
		}
    }
}
